package com.cdty.chess.service.impl;

import com.cdty.chess.model.SseMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;


@Component
public class SseEmitterManager {

    @Autowired
    NamedParameterJdbcTemplate template;

    @Autowired
    @Qualifier("sseTaskExecutor") // 指定使用配置的线程池
    private Executor asyncExecutor;

    // 修改为全局连接列表，使用线程安全集合
    private final Map<String, UserEmitter> userEmitters = new ConcurrentHashMap<>();

    public void addEmitter(SseEmitter emitter, String userId,String userName, boolean isAdmin) {
        //userEmitters.remove(userId); // 先移除旧连接
        UserEmitter userEmitter = new UserEmitter(emitter, userId, userName, isAdmin);
        userEmitters.put(userId, userEmitter);
        //this.getOnlineCount();
        // 连接关闭时清理
        emitter.onCompletion(() -> userEmitters.remove(userId));
        emitter.onTimeout(() -> userEmitters.remove(userId));
    }
    public void broadToAll(String eventName, Map<String,Object> betData) {
        userEmitters.forEach((userId, userEmitter) -> {
                try {
                    Map<String,Object> map = new HashMap<>();
                    map.put("event", eventName);
                    map.put("data", betData);
                    userEmitter.emitter.send(SseEmitter.event().name("chessBoard").data(map));
                } catch (IOException e) {
                    userEmitters.remove(userId); // 发送失败时移除
                }
        });
    }

    public void broadToMaster(String eventName, Map<String,String> betData) {
        userEmitters.forEach((userId, userEmitter) -> {
                try {
                    if (userEmitter.isAdmin ) {
                        //saveMessageToDB(eventName, "master", betData);
                        userEmitter.emitter.send(SseEmitter.event()
                                .name(eventName)
                                .data(betData));
                    }
                    userEmitter.emitter.send(SseEmitter.event().name(eventName).data(betData));
                } catch (IOException e) {
                    userEmitters.remove(userId); // 发送失败时移除
                }
        });
    }

    public void broadToUid(String eventName,String uid, Map<String,String> betData) {
        userEmitters.forEach((userId, userEmitter) -> {
                try {
                    if (userId.equals(uid) ) {
                        //saveMessageToDB(eventName, "master", betData);
                        userEmitter.emitter.send(SseEmitter.event()
                                .name(eventName)
                                .data(betData));
                    }
                    userEmitter.emitter.send(SseEmitter.event().name(eventName).data(betData));
                } catch (IOException e) {
                    userEmitters.remove(userId); // 发送失败时移除
                }
        });
    }

    public void getOnlineCount() {
        // 创建结构化消息对象
        Map<String, Object> messageObj = new HashMap<>();
        messageObj.put("content", String.valueOf(userEmitters.size()));
        this.broadToAll("pCount",messageObj);
    }


    private static class UserEmitter {
        final SseEmitter emitter;
        final String userId;
        final String userName;
        final boolean isAdmin;

        UserEmitter(SseEmitter emitter, String userId, String userName, boolean isAdmin) {
            this.emitter = emitter;
            this.userId = userId;
            this.userName = userName;
            this.isAdmin = isAdmin;
        }
    }

    private void saveMessageToDB(String eventType, String receiverId, Map<String,String> message) {
        String sql = "INSERT INTO sse_message (event_type, receiver_id, message_content, created_time) " +
                "VALUES (:eventType, :receiverId, :content, NOW())";
        MapSqlParameterSource params = new MapSqlParameterSource()
                .addValue("eventType", eventType)
                .addValue("receiverId", receiverId)
                .addValue("content", message.get("content"));
        template.update(sql, params);
    }

}
